home *** CD-ROM | disk | FTP | other *** search
- comment| PBFILES.ASM for PowerBASIC 3.0b or later.
-
- Written by Brian McLaughlin. Released into public domain.
-
- DECLARE FUNCTION OpenF% (FileSpec$)
- DECLARE SUB CloseF (Handle%)
- DECLARE SUB GetF (Handle%, Bytes&, ToVariable AS ANY)
- DECLARE SUB PutF (Handle%, Bytes&, FromVariable AS ANY)
- DECLARE SUB GetStF (Handle%, ToStrng AS ANY)
- DECLARE SUB PutStF (Handle%, FromStrng AS ANY)
- DECLARE SUB LoadF (Handle%, Bytes&, ToSegment??)
- DECLARE SUB SaveF (Handle%, Bytes&, FromSegment??)
- DECLARE FUNCTION GetLineF$ (Handle%)
- DECLARE FUNCTION EndF% ()
- DECLARE SUB SaveLineF ()
- DECLARE FUNCTION SizeF& (Handle%)
- DECLARE FUNCTION GetLocF& (Handle%)
- DECLARE SUB SetLocF (Handle%, NewPtrLoc&)
- DECLARE SUB ClipF (Handle%, NewSize&)
- DECLARE SUB FlushF (Handle%)
- DECLARE SUB KillF (FileSpec$)
- DECLARE FUNCTION ErrorCode% ()
- DECLARE SUB SetErrorCode (ErrorCode%)
- DECLARE SUB SetBufferSize (Bytes%)
- DECLARE SUB SetPtrBase (PtrBase%)
- DECLARE FUNCTION GetPtrBase% ()
- DECLARE FUNCTION HandleF% ()
- DECLARE SUB SetAccessCode (AccessCode%)
-
- end comment|
-
-
- Code Segment Byte
- Assume CS:Code
-
- Extrn GETSTRLOC:FAR
- Extrn GETSTRALLOC:FAR
- Extrn RLSSTRALLOC:FAR
-
- LineHandle DW 0FFFFh ; set initial handle to -1
- BufHandle DW 0 ; handle of buffer string used by GetLineF
- ReturnHandle DW 0 ; handle of string returned by GetLineF
- BufSeg DW 0 ; segment allocated to the buffer
- BufOfs DW 0 ; offset allocated to the buffer
- BufSize DW 1FEEh ; sets initial buffer size at 8174 bytes
- BufFilled DW 0 ; number of bytes read into buffer most recently
- BufIndex DW 0 ; index to byte in buffer where scan starts
- RemainsLow DW 0 ; number of bytes remaining to be read into buffer
- RemainsHigh DW 0
- LinePtrLow DW 0 ; used by GetLineF as internal pointer
- LinePtrHigh DW 0
- LineError DW 0 ; flags when GetLineF was interrupted by error
- FileEnd DW 0 ; set by GetLineF, reported by EndF
- CreatedFile DW 0 ; used in OpenF
-
- Old24Segment DW 0 ; used by $CritInstall, $CritRemove
- Old24Offset DW 0 ; used by $CritInstall, $CritRemove
- LowWord DW 0 ; scratch variables
- HighWord DW 0
- Error DW 0 ; internal error code variable
- CritErrCode DW 0 ; used by $CritHandler, $CritCheck
- LastHandle DW 0 ; most recent handle opened by OpenF
- PtrBase DW 0 ; pointer base (initialize to zero)
- AccessCode DB 2 ; preset for read/write, compatibility mode
- StrData DB 65 DUP(0) ; holds ASCIIZ filenames
-
-
- PUBLIC OpenF, CloseF, FlushF, GetF, PutF, GetStF, PutStF, LoadF, SaveF
- PUBLIC SetLocF, GetLocF, SizeF, KillF, HandleF, SetErrorCode, ClipF
- PUBLIC SetBufferSize, GetLineF, EndF, SetAccessCode, SetPtrBase, GetPtrBase
- PUBLIC SaveLineF, ErrorCode
-
-
-
- comment |************************************************************
- *
- * Name: ErrorCode
- *
- * Type: FUNCTION
- * Parameters: none
- * Values returned: value of internal Error variable
- *
- *********************************************************************|
-
- ErrorCode PROC FAR ; returns most recent error code
- Mov AX, CS:Error
- Retf
- ErrorCode ENDP
-
-
- comment |************************************************************
- *
- * Name: SetErrorCode
- *
- * Type: SUB
- * Parameters: AccessCode% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SetErrorCode PROC FAR ; resets value of error code variable
- Push BP
- Mov BP, SP
- Les BX, [BP+6]
- Mov AX, ES:[BX] ; AX = new error code
- Mov CS:Error, AX ; reset Error to new value
- Pop BP
- Retf 4
- SetErrorCode ENDP
-
-
- comment |************************************************************
- *
- * Name: SetAccessCode
- *
- * Type: SUB
- * Parameters: AccessCode% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SetAccessCode PROC FAR ; lets programmer set file access code
- Push BP
- Mov BP, SP
- Les BX, [BP+6]
- Mov AX, ES:[BX] ; AX = new access code (as integer)
- Mov CS:AccessCode, AL; set AccessCode to new value (low byte only)
- Pop BP
- Retf 4
- SetAccessCode ENDP
-
-
- comment |************************************************************
- *
- * Name: SetPtrBase
- *
- * Type: SUB
- * Parameters: Switch% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SetPtrBase PROC FAR ; resets pointer base value to 1 or zero
- Push BP
- Mov BP, SP
- Mov CS:PtrBase, 0 ; assume base of zero
- Les BX, [BP+6] ; point ES:BX to PtrBase%
- Mov CX, ES:[BX]
- Jcxz BaseSet
- Mov CS:PtrBase, 1
- BaseSet:
- Pop BP
- Retf 4
- SetPtrBase ENDP
-
-
- comment |************************************************************
- *
- * Name: GetPtrBase
- *
- * Type: FUNCTION
- * Parameters: none
- * Values returned: value of internal PtrBase variable
- *
- *********************************************************************|
-
- GetPtrBase PROC FAR ; returns pointer base value
- Mov AX, CS:PtrBase
- Retf
- GetPtrBase ENDP
-
-
- comment |************************************************************
- *
- * Name: HandleF
- *
- * Type: FUNCTION
- * Parameters: none
- * Values returned: handle of last file opened by OpenF
- *
- *********************************************************************|
-
- HandleF PROC FAR ; returns handle of last file opened with OpenF
- Mov AX, CS:LastHandle
- Retf
- HandleF ENDP
-
-
- comment |************************************************************
- *
- * Name: EndF
- *
- * Type: FUNCTION
- * Parameters: none
- * Values returned: value of internal FileEnd variable
- *
- *********************************************************************|
-
- EndF PROC FAR ; returns value of CS:FileEnd, as set by GetLineF
- Mov AX, CS:FileEnd
- Retf
- EndF ENDP
-
-
- comment |************************************************************
- *
- * Name: SaveLineF
- *
- * Type: SUB
- * Parameters: none
- * Values returned: none
- *
- *********************************************************************|
-
- SaveLineF PROC FAR ; resets DOS file pointer to agree with GetLineF
- Call $ResetLinePtr
- SaveLineF ENDP
-
-
- comment |************************************************************
- *
- * Name: SetBufferSize
- *
- * Type: SUB
- * Parameters: BufferSize% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SetBufferSize PROC FAR
- Push BP
- Mov BP, SP
- Les BX, [BP+6]
- Mov AX, ES:[BX] ;AX = Bytes%
- Cmp AX, 1006 ;see if Bytes% is less than 1006 bytes
- Jl AdjustUp ; if so, go adjust it up to 1006 bytes
- Cmp AX, 32750
- Jg AdjustDown
- SetSize:
- Mov CS:BufSize, AX ; save it
- SetExit:
- Pop BP
- Retf 4
- AdjustUp:
- Mov AX, 1006 ;don't allow buffer size < 1006 bytes
- Jmp SHORT SetSize
- AdjustDown:
- Mov AX, 32750 ;don't allow buffer size > 32750 bytes
- Jmp SHORT SetSize
- SetBufferSize ENDP
-
-
- comment |************************************************************
- *
- * Name: OpenF
- *
- * Type: FUNCTION
- * Parameters: FileName$ (access at [BP+6])
- * Values returned: DOS handle for opened file
- *
- *********************************************************************|
-
- OpenF PROC FAR ; access FileName$ at [BP+6]
- Push BP
- Mov BP, SP
- Push SI
- Push DI
- Push DS
- Call $CritInstall
- Mov CS:CreatedFile, 0 ; assume the file FileName$ already exists
- Lds BX, [BP+6] ; DS:BX = address of FileName$ handle
- Mov AX, [BX] ; AX = handle of filename
- Push AX ; leave handle on stack for GETSTRLOC
- Call GETSTRLOC ; this puts address in DX:AX, length in CX
- Jcxz BadName ; oops! no name of a file to open
- Cmp CX, 64 ; see if FileName$ + CHR$(0) will fit in StrData
- Ja BadName ; if not, we can't process it
- Mov DS, DX
- Mov SI, AX ;DS:SI point to first byte of filename
- Push CS
- Pop ES ; point ES at code seg, where StrData resides
- Mov DI, Offset StrData ;ES:DI points to start of StrData
- Rep Movsb ; put a copy of name in StrData
- Mov ES:[DI], CL ; put a zero char at end of filename in StrData
- OpenFile:
- Mov AH, 3Dh ; we'll try to open the file with DOS service 3Dh
- Mov AL, AccessCode ; put access code we'll use into AL
- Push CS
- Pop DS ; set DS = CS
- CreateFile: ; CX = 0 = normal file attribute (if creating)
- Mov DX, Offset StrData ;DS:DX points to ASCIIZ filename in CS:StrData
- Int 21h ; call DOS to either open or create FileName$
- Call $CritCheck ; check for errors
- Jc OpenError ; if no error AX = file handle
- Cmp CS:CreatedFile, 0 ; see if the file we opened was just created
- Jne CloseNewFile ; if it was, we need to close it and reopen it
- Mov CS:LastHandle, AX ; otherwise, save a copy of the handle
- OpenExit: ; and exit
- Call $CritRemove
- Pop DS
- Pop DI
- Pop SI
- Pop BP
- Retf 4
- OpenError:
- Cmp AX, 2 ; was it a "file not found" error (2)?
- Jne RealError ; was a different error than "file not found"
- Mov AX, 3C00h ; otherwise, call DOS service to create file
- Mov CS:CreatedFile, -1 ;flag that we are creating a new file
- Jmp SHORT CreateFile ; go back and create the file FileName$
- BadName:
- Mov AX, 2 ; if FileName$ unusable return "file not found"
- RealError:
- Mov CS:Error, AX ; dump error code into Error
- Xor AX, AX ; put 0 where handle expected
- Jmp SHORT OpenExit ; return
- CloseNewFile:
- Mov BX, AX ; put the new file's handle in BX
- Mov AX, 3E00h ; close the newly created file
- Int 21h
- Call $CritCheck
- Jc RealError
- Mov CS:CreatedFile, 0 ; now flag that the file is ALREADY created
- Jmp SHORT OpenFile ; and re-open it with proper access code
- OpenF ENDP
-
-
- comment |************************************************************
- *
- * Name: CloseF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- CloseF PROC FAR ; access Handle% at [BP+6]
- Push BP
- Mov BP, SP
- Call $CritInstall
- Les BX, [BP+6] ; ES:BX point to Handle%
- Mov BX, ES:[BX] ; BX = Handle%
- Cmp BX, 5 ; don't close the DOS reserved handles (0-4)
- Jb CloseExit ; just quietly do nothing and exit
- Cmp BX, CS:LineHandle ; see if this handle is last one read by GetLineF
- Je ResetLineHandle ; if it is, reset the CS:LineHandle variable
- ResumeClose:
- Mov AX, 3E00h ; DOS close file service
- Int 21h
- Call $CritCheck
- Jc CloseError
- CloseExit:
- Call $CritRemove
- Pop BP
- Retf 4
- CloseError:
- Mov CS:Error, AX
- Jmp SHORT CloseExit
- ResetLineHandle:
- Mov CS:LineHandle, 0FFFFh
- Jmp SHORT ResumeClose
- CloseF ENDP
-
-
- comment |************************************************************
- *
- * Name: FlushF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- FlushF PROC FAR ; access Handle% at [BP+6]
- Push BP
- Mov BP, SP
- Call $CritInstall
- Les BX, [BP+6]
- Mov BX, ES:[BX] ; BX = Handle%
- Mov AH, 45h ; AH = service 45h of DOS
- Int 21h ; opens a duplicate handle for a file
- Call $CritCheck ; and returns it in AX
- Jc FlushError
- Mov BX, AX ;BX = dupe handle returned by DOS
- Mov AH, 3Eh ; now call close handle service
- Int 21h ; to close the duplicate handle,
- Call $CritCheck ; which flushes DOS buffers to disk,
- Jc FlushError ; without closing the original handle
- FlushExit:
- Call $CritRemove
- Pop BP
- Retf 4
- FlushError:
- Mov CS:Error, AX
- Jmp SHORT FlushExit
- FlushF ENDP
-
-
- comment |************************************************************
- *
- * Name: GetF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+14])
- * Bytes& (access at [BP+10])
- * ToVariable (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- GetF PROC FAR
- Push BP
- Mov BP, SP
- Call $CritInstall
- Push DS
- Push SI
- Lds BX, [BP+10] ; DS:BX points to Bytes&
- Mov AX, [BX] ; put Bytes& into DX:AX
- Mov DX, [BX+2]
- Cmp DX, 0 ; see if we are dealing with a negative Bytes&
- Jl ReadExit
- Or AX, AX
- Jnz GetBytesNotZero
- Or DX, DX
- Jz ReadExit
- GetBytesNotZero:
- Lds BX, [BP+14] ; DS:BX points to Handle%
- Mov BX, [BX] ; Handle% in BX
- Mov CX, AX ; CX = low byte of Bytes&
- And CX, 7FFFh ; CX = any remainder < 32K bytes
- Push CX ; save that value for later
- Mov CX, 15 ; loop counter for Shr loop
- Top:
- Shr DX, 1
- Rcr AX, 1
- Loop Top ; divides DX:AX by 32K
- Lds DX, [BP+6] ; load DS:DX with address to read file into
- Mov CX, AX ;CX = result of Bytes& \ 32K
- Jcxz LessThan32K ; if zero then LOF was < 32K
- Top2:
- Push CX ; save loop counter
- Mov CX, 8000h ; CX = 32K bytes to copy
- Mov AX, 3F00h ; DOS read from file service
- Int 21h ; BX still contains Handle% still
- Call $CritCheck ;
- Jc ReadError ; must clean up stack, if error occurs here
- Mov CX, DS ; we need to adjust segment upward
- Add CX, 2048 ; 2K paragraphs = 32K bytes
- Mov DS, CX ; DS now points to proper segment
- Pop CX ; resume loop counter
- Loop Top2
- LessThan32K:
- Pop CX ; this puts remainder into CX
- Mov AX, 3F00h ; DOS "read from file" service
- Int 21h
- Call $CritCheck
- Jc ReadError2 ; stack has no extra pushes on it
- ReadExit:
- Pop SI
- Pop DS
- Call $CritRemove
- Pop BP
- Retf 12 ; remove three parameters
- ReadError:
- Add SP, 4 ; remove the residue of two pushes
- ReadError2:
- Mov CS:Error, AX ; leave error code for ErrorCode% to find
- Jmp SHORT ReadExit
- GetF ENDP
-
-
- comment |************************************************************
- *
- * Name: PutF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+14])
- * Bytes& (access at [BP+10])
- * FromVariable (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- PutF PROC FAR
- Push BP
- Mov BP, SP
- Call $CritInstall
- Push DS
- Push SI
- Lds BX, [BP+14] ; DS:BX = address of Handle%
- Mov BX, [BX] ;BX = handle of file to write to
- Lds SI, [BP+10] ; DS:SI = address of Bytes&
- Mov AX, [SI] ;AX = low word of Bytes&
- Mov DX, [SI+2] ;DX:AX = Bytes&
- Cmp DX, 0 ; see if we are dealing with a negative Bytes&
- Jl WriteExit ; if so, exit
- Or AX, AX ; see if Bytes& = 0
- Jnz PutBytesNotZero
- Or DX, DX
- Jz WriteExit ; if Bytes& = 0, then exit
- PutBytesNotZero:
- Mov CX, AX ;CX = low word of Bytes&
- And CX, 7FFFh ; CX = any remainder < 32K
- Push CX ; save it for later
- Mov CX, 15 ; loop counter
- LoopTop:
- Shr DX, 1 ; shift-divide DX:AX by 32K
- Rcr AX, 1
- Loop LoopTop
- Lds DX, [BP+6] ; DS:DX points to memory block to write to disk
- Mov CX, AX ; CX = number of 32K blocks to write to disk
- Or AX, AX ; was Bytes& >= 32K?
- Jnz LoopTop2 ; if so, jump to take care of it
- NotOver32K:
- Pop CX ; this puts remainder into CX
- Mov AX, 4000h ; DOS write to file service
- Int 21h
- Call $CritCheck
- Jc WriteError2 ; stack has no extra pushes
- WriteExit:
- Pop SI
- Pop DS
- Call $CritRemove
- Pop BP
- Retf 12
- WriteError:
- Add SP, 4 ; remove the residue of two pushes
- WriteError2:
- Mov CS:Error, AX
- Jmp SHORT WriteExit ; leave error code for ErrorCode% to find
- LoopTop2:
- Push CX ; save loop counter
- Mov CX, 8000h ; CX = 32K bytes to copy
- Mov AX, 4000h ; DOS write to file service
- Int 21h ; BX still contains Handle%
- Call $CritCheck ;
- Jc WriteError ; stack must be cleaned up, if error here
- Mov CX, DS ; we need to adjust segment upward
- Add CX, 2048 ; 2K paragraphs = 32K bytes
- Mov DS, CX ;
- Pop CX ; restore loop counter
- Loop LoopTop2
- Jmp SHORT NotOver32K
- PutF ENDP
-
-
- comment |************************************************************
- *
- * Name: GetStF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+10])
- * ToString (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- GetStF PROC FAR
- Push BP
- Mov BP, SP
- Les AX, [BP+10] ; ES:AX points to Handle%
- Push ES
- Push AX ; push both segment and offset for GetF
- Les BX, [BP+6] ; ES:BX = address of string-handle for ToStrng
- Mov AX, ES:[BX] ; AX = handle of string
- Push AX
- Call GETSTRLOC ; puts seg:off in DX:AX, length into CX
- Mov CS:HighWord, 0 ; zero the high word variable, so we can ...
- Mov CS:LowWord, CX ; send length of ToStrng to GetF as Bytes&
- Mov BX, Offset LowWord ; and push a pointer to it onto stack
- Push CS ; CS:BX points to highword/lowword of "Bytes&"
- Push BX ; and DX:AX point to ToStrng
- Push DX ; push 'em both as a ToVariable for GetF
- Push AX
- Call FAR PTR GetF ; make it a far call
- Pop BP
- Retf 8
- GetStF ENDP
-
-
- comment |************************************************************
- *
- * Name: PutStF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+10])
- * FromString (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- PutStF PROC FAR ; access Handle% at [BP+10]
- Push BP ; FromStrng at [BP+6]
- Mov BP, SP
- Les AX, [BP+10] ; ES:AX points to Handle%
- Push ES
- Push AX ; push both segment and offset for GetF
- Les BX, [BP+6] ; ES:BX = address of string-handle for FromStrng
- Mov AX, ES:[BX] ; AX = handle of string
- Push AX
- Call GETSTRLOC ; puts seg:off in DX:AX, length into CX
- Mov CS:HighWord, 0 ; zero the high word variable, so we can ...
- Mov CS:LowWord, CX ; send length of FromStrng to GetF as Bytes&
- Mov BX, Offset LowWord ; and push a pointer to it onto stack
- Push CS ; CS:BX points to highword/lowword of "Bytes&"
- Push BX ; and DX:AX point to FromStrng
- Push DX ; push 'em both as a FromVariable for GetF
- Push AX
- Call FAR PTR PutF ; make it a far call
- Pop BP
- Retf 8
- PutStF ENDP
-
-
- comment |************************************************************
- *
- * Name: SaveF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+14])
- * Bytes& (access at [BP+10])
- * FromSegment?? (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SaveF PROC NEAR
- Push BP
- Mov BP, SP
- Les AX, [BP+14]
- Push ES ;push address of Handle%
- Push AX
- Les AX, [BP+10]
- Push ES ;push address of Bytes&
- Push AX
- Les BX, [BP+6]
- Mov AX, ES:[BX]
- Push AX ;push value of FromSegment??
- Xor AX, AX ;assume offset of 0
- Push AX ;push value of offset
- Call FAR PTR PutF
- Pop BP
- Retf 12
- SaveF ENDP
-
-
- comment |************************************************************
- *
- * Name: LoadF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+14])
- * Bytes& (access at [BP+10])
- * ToSegment?? (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- LoadF PROC NEAR
- Push BP
- Mov BP, SP
- Les AX, [BP+14]
- Push ES ;push address of Handle%
- Push AX
- Les AX, [BP+10]
- Push ES ;push address of Bytes&
- Push AX
- Les BX, [BP+6]
- Mov AX, ES:[BX]
- Push AX ;push value of ToSegment??
- Xor AX, AX ;assumes offset of 0
- Push AX ;push value of offset
- Call FAR PTR GetF
- Pop BP
- Retf 12
- LoadF ENDP
-
-
- comment |************************************************************
- *
- * Name: SetLocF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+10])
- * NewPtrLoc& (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- SetLocF PROC FAR ;access Handle% at [BP+10]
- Push BP ; NewPtrLoc& at [BP+6]
- Mov BP, SP
- Call $CritInstall
- Les BX, [BP+6] ; load address of NewPtrLoc&
- Mov DX, ES:[BX] ; low word of NewPtrLoc& into DX
- Mov CX, ES:[BX+2] ; high word of NewPtrLoc& into CX
- Sub DX, CS:PtrBase ; PtrBase could be 1 or 0
- Sbb CX, 0 ; so, adjust for current pointer base
- Les BX, [BP+10] ; load the address of Handle%
- Mov BX, ES:[BX] ; BX = Handle%
- Mov AX, 4200h ; we're moving from start of file
- Int 21h ; call DOS
- Call $CritCheck ; look for critical errors
- Jc SetLocError ; if carry set, there was an error
- SetLocExit:
- Call $CritRemove
- Pop BP
- Retf 8
- SetLocError:
- Mov CS:Error, AX
- Jmp SHORT SetLocExit
- SetLocF ENDP
-
-
- comment |************************************************************
- *
- * Name: GetLocF
- *
- * Type: FUNCTION
- * Parameters: Handle% (access at [BP+6])
- * Values returned: current location of pointer in file: Handle%
- *
- *********************************************************************|
-
- GetLocF PROC FAR
- Push BP
- Mov BP, SP
- Push DS
- Call $CritInstall
- Lds BX, [BP+6] ; address of Handle%
- Mov BX, [BX] ; BX = Handle%
- Xor DX, DX
- Xor CX, CX ; tell DOS we'll be moving zero bytes
- Mov AX, 4201h ; from the present file position
- Int 21h
- Call $CritCheck
- Jc GetLocError ; if no error DX:AX contains location
- Add AX, CS:PtrBase ; adjust location to fit current pointer base
- Adc DX, 0 ; before returning
- GetLocExit:
- Call $CritRemove
- Pop DS
- Pop BP
- Retf 4
- GetLocError:
- Mov CS:Error, AX ; put AX into Error for ErrorCode%
- Xor AX, AX ; put a file location of 0
- Xor DX, DX ; into DX:AX
- Jmp SHORT GetLocExit
- GetLocF ENDP
-
-
- comment |************************************************************
- *
- * Name: SizeF
- *
- * Type: FUNCTION
- * Parameters: Handle% (access at [BP+6])
- * Values returned: current size of file: Handle%
- *
- *********************************************************************|
-
- SizeF PROC FAR
- Push BP
- Mov BP, SP
- Call $CritInstall
- Les BX, [BP+6] ; get address of Handle from stack
- Mov BX, ES:[BX] ; put Handle in BX
- Xor CX, CX ; CX:DX show how many bytes to move
- Xor DX, DX ; the file pointer during next call
- Mov AX, 4201h ; to DOS move-pointer service (42h)
- Int 21h ; we're moving it zero bytes this time
- Call $CritCheck
- Jc SizeError
- Mov CS:LowWord, AX ; save current file pointer position
- Mov CS:HighWord, DX ; into memory for later
- Xor DX, DX ; Now we'll move zero bytes again, but
- Xor CX, CX ; this time to zero bytes from the EOF
- Mov AX, 4202h ; move pointer service (offset from end)
- Int 21h ; this operation points DX:AX at the last
- Call $CritCheck ; byte of file (as an offset from start)
- Jc SizeError
- Xchg CS:LowWord, AX ; now let's save it, and restore pointer
- Xchg CS:HighWord, DX ; to the old position
- Mov CX, DX ; put the high byte into CX first
- Mov DX, AX ; and the low byte into DX
- Mov AX, 4200h ; this time move from the start of file!
- Int 21h
- Call $CritCheck
- Jc SizeError
- Mov AX, CS:LowWord ; put the LOF into DX:AX
- Mov DX, CS:HighWord
- SizeExit:
- Call $CritRemove ; preserves state of carry flag
- Pop BP
- Ret 4
- SizeError:
- Mov CS:Error, AX ; put error code from AX into it
- Xor AX, AX ; put length of 0 into DX:AX
- Xor DX, DX ; which is better than a random value
- Stc ; when ClipF calls, this flags the error
- Jmp SHORT SizeExit ; now return
- SizeF ENDP
-
-
- comment |************************************************************
- *
- * Name: ClipF
- *
- * Type: SUB
- * Parameters: Handle% (access at [BP+10])
- * NewSize& (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- ClipF PROC FAR
- Push BP
- Mov BP, SP
- Les AX, [BP+10] ; ES:AX = address of Handle%
- Push ES
- Push AX ; push the pointer back onto the stack for SizeF
- Call FAR PTR SizeF ; returns size in HighWord:LowWord and DX:AX
- Jc BareExit ; if carry set, exit without calling $CritRemove
- Call $CritInstall ; this trashes DX:AX
- Mov AX, CS:LowWord
- Mov DX, CS:HighWord ; DX:AX = size of file
- Les BX, [BP+6] ; ES:BX = address of NewSize&
- Mov CX, ES:[BX] ; get low byte into CX
- Mov BX, ES:[BX+2] ; get high byte in BX, BX:CX = NewSize&
- Call $CmpLongInt ; sets carry if BC:CX > DX:AX
- Jnc NewSizeOK ; if carry not set, NewSize is <= file size
- Mov CX, AX ; otherwise, substitute file size for NewSize&
- Mov BX, DX ; now BX:CX = file size
- NewSizeOK:
- Mov DX, CX
- Mov CX, BX ; now CX:DX = byte to clip to (zero-based)
- Les BX, [BP+10] ; ES:BX = address of Handle%
- Mov BX, ES:[BX] ; BX = Handle%
- Mov AX, 4200h
- Int 21h ; sets pointer to CX:DX in handle BX file
- Call $CritCheck
- Jc ClipError
- Xor CX, CX ; writing zero bytes (BX = Handle%)
- Mov AX, 4000h ; DOS write to file service
- Int 21h ; clip it!
- Call $CritCheck ; any errors?
- Jc ClipError
- ClipExit:
- Call $CritRemove
- BareExit:
- Pop BP
- Retf 8
- ClipError:
- Mov CS:Error, AX ; save the error code
- Jmp SHORT ClipExit
- ClipF ENDP
-
-
- comment |************************************************************
- *
- * Name: KillF
- *
- * Type: SUB
- * Parameters: FileName$ (access at [BP+6])
- * Values returned: none
- *
- *********************************************************************|
-
- KillF PROC FAR
- Push BP
- Mov BP, SP
- Push DS
- Push SI
- Push DI
- Call $CritInstall
- Les BX, [BP+6] ; load address of FileName$'s string-handle
- Mov AX, ES:[BX] ;AX = handle
- Push AX
- Call GETSTRLOC ; returns address in DX:AX, length in CX
- Jcxz KillBadName ; oops! no name for the file to kill
- Cmp CX, 64 ; check to see if FileName$ + CHR$(0) <= 65
- Ja KillBadName ; if not, we can't process it
- Mov DS, DX
- Mov SI, AX ;DS:SI point to first byte of Filename$
- Mov AX, CS
- Mov ES, AX ;point ES at code seg
- Mov DI, Offset CS:StrData ;ES:DI point to StrData
- Mov DX, DI ; DX points to StrData (for Int call later)
- Rep Movsb ; puts copy of name in StrData
- Mov [DI], CL ; puts zero char at end of filename
- Mov DS, AX ; DS:DX point to ASCIIZ filename in StrData
- Mov AH, 41h ; prepare to call DOS delete file function
- Int 21h
- Call $CritCheck
- Jc KillError ; if carry set, there was an error
- KillExit:
- Call $CritRemove
- Pop DI ; do the rest of the clean-up
- Pop SI
- Pop DS
- Pop BP
- Retf 4
- KillBadName:
- Mov AX, 2 ; error code for "file not found"
- KillError:
- Mov CS:Error, AX ; put error code into Error
- Jmp SHORT KillExit
- KillF ENDP
-
-
- comment |************************************************************
- *
- * Name: GetLineF
- *
- * Type: FUNCTION
- * Parameters: Handle% (access at [BP+6])
- * Values returned: one line of text from: Handle%
- *
- *********************************************************************|
-
- GetLineF PROC FAR
- Push BP
- Mov BP, SP
- Push DS
- Push DI
- Push SI
- Les BX, [BP+6] ; ES:BX = Handle% address
- Mov BX, ES:[BX] ;BX = Handle% value
- Cmp BX, 5 ; check if Handle% is a DOS reserved handle
- Jb BadHandle ; if so, just return AX = null string
- Cmp BX, CS:LineHandle ;is this file handle one we're already reading?
- Je OldHandle
- Jmp NewHandle ;if it's a new handle, go initialize buffer, etc.
- OldHandle:
- Cmp CS:LineError, 0 ;if last attempt to read resulted in an error
- Jne ResumeAfterError ;then go try to pick up where we left off
- Initialized:
- Mov AX, CS:BufSeg
- Mov DS, AX ; DS does NOT point to the data segment now
- Mov ES, AX ; point ES at buffer, too
- Mov DI, CS:BufIndex ;ES:DI point to starting byte of next scan
- Mov CX, CS:BufFilled ;CX = total bytes read into the buffer
- Add CX, CS:BufOfs
- Sub CX, DI ;CX = bytes left to scan in buffer
- Cmp CX, 256 ; are there more than 256 bytes left to scan?
- Jb NearBufEnd ; if so, stop and refill the buffer, if necessary
- Mov CX, 256 ; don't scan more than 256 bytes at a time
- NearFileEnd:
- Mov DX, CX ; save the initial value of CX in DX (for later)
- Xor BX, BX ; assume no carriage return will be found
- Mov AL, 13 ;scan for a carriage return char - CHR$(13)
- Repne Scasb ;repeat CX times or until there's a match
- Jnz NoCRFound ;if NO CHR$(13), zero flag is clear (and CX=0)
- Sub DX, CX ;subtract bytes beyond CHR$(13) from bytes scanned
- Dec DX ;DX = num of bytes from BufIndex to first CHR$(13)
- Mov BX, 2 ; adjusts BufIndex for one CR/LF pair
- NoCRFound:
- Call $StringFill ; this routine creates return string
- Add DX, BX ; BX = either 0 or 2, depending if CR found
- Add CS:BufIndex, DX ; BufIndex points to char to start next scan with
- Mov CX, CS:BufFilled ; calculate if we're at the last byte or none
- Sub CX, CS:BufIndex
- Add CX, CS:BufOfs
- Jcxz SetEOF
- Add CS:LinePtrLow, DX
- Adc CS:LinePtrHigh, 0
- BufExit:
- Mov AX, CS:ReturnHandle ;return the handle of Return$
- Pop SI
- Pop DI
- Pop DS
- Pop BP
- Retf 4
- BadHandle:
- Mov CS:Error, 6 ; record an "invalid handle" error
- WasError: ; jumps here whenever an error occurs
- Mov CS:ReturnHandle, 0 ; return a null string
- Mov CS:LineError, 1 ; flag that an error interupted processing
- Jmp SHORT BufExit ; now we can exit the procedure
- ResumeAfterError:
- Call $ResetLinePtr ; after an error, try to reset DOS pointer
- NewHandle:
- Call $InitHandle ; initialize a new buffer & internal variables
- Jc WasError ; if carry set, $InitHandle had an error
- Mov AX, CS:BufSeg
- Mov DS, AX ; DS points to buffer segment now
- Call $FillBuffer ; fills buffer, resets BufIndex, BufFilled
- Jc WasError ; if carry set, $FillBuffer had an error
- Or AX, AX ; AX = bytes read into buffer
- Jz SetEOF
- Jmp Initialized ;go back to scan buffer for first return string
- NearBufEnd:
- Cmp CS:RemainsLow, 0
- Jne BufRefill ; if RemainsLow > 0, we need to refill buffer
- Cmp CS:RemainsHigh, 0 ; if low byte = 0, we need to look at the high byte
- Jne BufRefill
- Jmp NearFileEnd
- BufRefill:
- Add CS:RemainsLow, CX
- Adc CS:RemainsHigh, 0
- Call $FillBuffer ; fills buffer, resets BufIndex, BufFilled
- Jc WasError ; if carry set, $FillBuffer had an error
- Jmp Initialized ; jump (long) to start over with new values
- SetEOF:
- Call $ReleaseMem ;give buffer memory back to PB
- Mov CS:FileEnd, 0FFFFh ;set the EOF marker = (-1)
- Mov CS:LineHandle, 0FFFFh ;set file handle to impossible number (-1)
- Jmp SHORT BufExit
- GetLineF ENDP
-
-
- comment |************************************************************
- *
- * Name: $StringFill
- *
- * Type: internal near PROC
- * Registers altered: AX, CX, ES, SI, DI
- *
- *********************************************************************|
-
- $StringFill PROC NEAR ; enter with DS=BufSeg
- Push DX ;this push is to save DX from trashing!
- Push DX ;DX = desired length of return string upon entry
- Call GETSTRALLOC ; allocate a return string of that length
- Mov CS:ReturnHandle, AX ; save the handle
- Or AX, AX ;was it a zero?
- Jz StrExit
- Push AX
- Call GETSTRLOC ; now find where it is, so we can fill it
- Mov ES, DX ; point ES:DI at it
- Mov DI, AX ; (after allocation, CX = length of return string)
- Jcxz StrExit ; if null, we can just exit now
- Mov SI, CS:BufIndex ; or, let's point DS:SI at start byte of last scan
- Shr CX, 1 ; convert CX to words
- Rep Movsw ; and copy CX words into Return$
- Jc WriteLastByte
- StrExit:
- Pop DX ;restore DX before continuing
- Retn
- WriteLastByte:
- Inc CX
- Rep Movsb
- Jmp SHORT StrExit
- $StringFill ENDP
-
-
- comment |************************************************************
- *
- * Name: $ResetLinePtr
- *
- * Type: internal near PROC
- * Registers altered: AX, BX, CX, DX, ES
- *
- *********************************************************************|
-
- $ResetLinePtr PROC NEAR
- Call $CritInstall
- Mov DX, CS:LinePtrLow
- Mov CX, CS:LinePtrHigh
- Mov BX, CS:LineHandle
- Mov AX, 4200h
- Int 21h
- Call $CritCheck
- Jc ResetPtrError
- Mov CS:LineError, 0
- ResetPtrExit:
- Call $CritRemove
- Retn
- ResetPtrError:
- Mov CS:Error, AX
- Mov CS:LineError, 1
- Jmp SHORT ResetPtrExit
- $ResetLinePtr ENDP
-
-
- comment |************************************************************
- *
- * Name: $FillBuffer
- *
- * Type: internal near PROC
- * Registers altered: AX, BX, CX, DX, DI, SI
- *
- *********************************************************************|
-
- $FillBuffer PROC NEAR ; assumes DS = BufSeg
- Call $CritInstall
- Call $ResetLinePtr
- Mov BX, CS:LineHandle ; we need the handle in BX for DOS call
- Mov DX, CS:BufOfs ;point DS:DX at buffer's first byte for DOS call
- Mov CS:BufIndex, DX ;whenever buffer is filled index reset to BufOfs
- Mov CX, CS:BufSize ;fill the buffer with CX bytes from file
- Mov AX, 3F00h ;request read-file service
- Int 21h ; from DOS -- returns bytes read in AX
- Call $CritCheck
- Jc FillBufError ; if carry flag set, the buffer isn't filled
- Sub CS:RemainsLow, AX ;show there are AX fewer bytes left in file
- Sbb CS:RemainsHigh, 0 ;make certain high word also reflects the subtract
- Mov CS:BufFilled, AX ; if not, save actual BufFilled
- FillBufExit:
- Call $CritRemove
- Retn
- FillBufError:
- Mov CS:Error, AX ; save the error
- Jmp SHORT FillBufExit
- $FillBuffer ENDP
-
-
- comment |************************************************************
- *
- * Name: $ReleaseMem
- *
- * Type: internal near PROC
- * Registers altered: AX (plus any altered by RLSSTRALLOC)
- *
- *********************************************************************|
-
- $ReleaseMem PROC NEAR
- Mov AX, CS:BufHandle
- Push AX
- Call RLSSTRALLOC ; try to release the current buffer back to PB
- Or AX, AX ; when AX <> 0, the string was released
- Jz NotReleased ; if we can't release it, we'll reuse it
- Mov CS:BufHandle, 0 ; reset the handle as "no handle allocated"
- NotReleased:
- Retn
- $ReleaseMem ENDP
-
-
- comment |************************************************************
- *
- * Name: $InitHandle
- *
- * Type: internal near PROC
- * Registers altered: AX, BX, CX, DX, ES
- *
- *********************************************************************|
-
- $InitHandle PROC NEAR
- Mov CS:LineHandle, BX ; save this file handle as current handle
- Mov CS:FileEnd, 0 ; zero this variable when there's a new file
- Call $CritInstall ; this trashes BX
- Mov BX, CS:LineHandle ; so resore it back to file handle
- Xor DX, DX
- Xor CX, CX ; tell DOS we'll be moving zero bytes
- Mov AX, 4201h ; from the present file position
- Int 21h
- Call $CritCheck
- Jc InitError
- Mov CS:LinePtrLow, AX
- Mov CS:LinePtrHigh, DX
- Push AX ; save 'em on the stack, too
- Push DX
- Mov AX, Offset CS:LineHandle
- Push CS ; push seg:off address of CS:LineHandle
- Push AX
- Call FAR PTR SizeF
- Jc InitExit ; error code already saved, just exit
- Pop BX
- Pop CX ; BX:CX = ptr location in file
- Sub AX, CX
- Sbb DX, BX ; DX:AX = bytes remaining from ptr to end
- Mov CS:RemainsLow, AX ; save that value in RemainsHigh:RemainsLow
- Mov CS:RemainsHigh, DX
- Mov AX, CS:BufHandle ; do we already have a buffer allocated?
- Or AX, AX ; if so, it was because we couldn't release it!
- Jnz UsePrevBuffer ; so we'll just go ahead and reuse it
- Mov BX, CS:BufSize ;BX = length of buffer in bytes
- Push BX ; push bytes requested for GETSTRALLOC
- Call GETSTRALLOC ; allocate a buffer string
- Or AX, AX ; see if the allocation worked (if not, AX=0)
- Jz NoBuffer ; if there's no buffer string, bail out now
- Mov CS:BufHandle, AX ; save the string handle for later release
- UsePrevBuffer:
- Push AX ; push string handle for GETSTRLOC
- Call GETSTRLOC ; find our string/buffer
- Mov CS:BufSeg, DX ; nail down the Seg:Ofs address
- Mov CS:BufOfs, AX
- Mov CS:BufIndex, AX ; point index at first byte of buffer, too
- Mov CS:BufFilled, CX ; assume all the buffer will be used, adjust later
- Mov CS:BufSize, CX ; save buffer size, in case using prev buffer
- InitExit:
- Call $CritRemove
- Retn
- InitError:
- Mov CS:Error, AX ; save the error
- Jmp SHORT InitExit ; carry flag already set
- NoBuffer:
- Mov CS:Error, -1 ; let AX = -1 when string allocation fails
- Stc ; set the carry flag to flag the error
- Jmp SHORT InitExit ; and return -1 as the "error number"
- $InitHandle ENDP
-
-
- comment |************************************************************
- *
- * Name: $CmpLngInt
- *
- * Type: internal near PROC
- * Registers altered: flags register
- *
- *********************************************************************|
-
- $CmpLongInt PROC NEAR
- Cmp BX, DX ; begin to compare DX:AX to BX:CX
- Jg BXCXMore ; if BX > DX then BX:CX > DX:AX
- Cmp DX, BX ; see if DX > BX
- Jg BXCXNotMore ; if DX = BX this falls through to next compare
- Cmp AX, CX ; compare low words, using unsigned comparison
- Jb BXCXMore ; if AX < CX then BX:CX is greater
- BXCXNotMore:
- Clc ; clear carry when BX:CX <= DX:AX
- CmpExit:
- Retn ; and return
- BXCXMore:
- Stc ; set carry when BX:CX > DX:AX
- Jmp SHORT CmpExit
- $CmpLongInt ENDP
-
-
- comment |************************************************************
- *
- * Name: $CritInstall
- *
- * Type: internal near PROC
- * Registers altered: AX, BX, DX, ES
- *
- *********************************************************************|
-
- $CritInstall PROC NEAR
- Push DS ; DON'T trash DS!
- Mov CS:CritErrCode, 0 ; make sure CritErrCode is zeroed out
- Mov AX, 3524h ; call DOS service to return current
- Int 21h ; interrupt vector
- Mov CS:Old24Offset, BX ; save that vector for later
- Mov CS:Old24Segment, ES
- Push CS
- Pop DS ; point DS:DX at new interrupt handler
- Mov DX, Offset $CritHandler
- Mov AX, 2524h ; call DOS service to set new vector
- Int 21h ; all set (DOS returns no values here)
- Pop DS ; so restore everything we tampered with
- Retn
- $CritInstall ENDP
-
-
- comment |************************************************************
- *
- * Name: $CritHandler
- *
- * Type: internal near PROC
- * Registers altered: AL
- *
- *********************************************************************|
-
- $CritHandler PROC FAR
- Push AX ; do as little damage as possible
- Mov AX, DI ; when handler called, error code in DI
- Inc AX ; must show something is there if code=0
- Mov CS:CritErrCode, AX ; store it in memory for later retrieval
- Pop AX ; this ensures AH is preserved
- Xor AL, AL ; returning zero in AL instructs DOS to
- Iret ; ignore the error
- $CritHandler ENDP
-
-
- comment |************************************************************
- *
- * Name: $CritCheck
- *
- * Type: internal near PROC
- * Registers altered: AX (only if error code detected)
- *
- *********************************************************************|
-
- $CritCheck PROC NEAR ; trashes nothing, returns error code in AX
- PushF ; the flags will change during this proc
- Cmp CS:CritErrCode, 0 ; look for an error
- Jne IsCritError
- PopF ; restore flags and go
- CritError:
- Retn
- IsCritError:
- Mov AX, CS:CritErrCode ; return error in AX
- Add AX, 18 ; make it a standard error code
- PopF ; restore all flags, before setting carry flag
- Stc ; flag a live one with carry
- Jmp SHORT CritError
- $CritCheck ENDP
-
-
- comment |************************************************************
- *
- * Name: $CritRemove
- *
- * Type: internal near PROC
- * Registers altered: none
- *
- *********************************************************************|
-
- $CritRemove PROC NEAR
- Push DS
- Push DX ; don't trash DX:AX!! IMPORTANT
- Push AX
- PushF ; preserve flags register
- Mov AX, CS:Old24Segment
- Mov DS, AX ; point DS:DX at old interrupt handler
- Mov DX, CS:Old24Offset
- Mov AX, 2524h ; call DOS service to set the vector
- Int 21h ; all set / DOS returns no values here
- PopF
- Pop AX
- Pop DX
- Pop DS
- Retn
- $CritRemove ENDP
-
- Code ENDS
- END
-